package controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import utils.Utils;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.view.View;
import android.widget.Toast;
import app.cloudstringers.Home;
import app.cloudstringers.PriorityList;
import app.cloudstringers.R;
import define.API;
import define.Class;
import define.Constants;
import define.Key;

public class CheckHBAsync extends AsyncTask<String, Void, Boolean> {
	/**
	 * String section
	 */
	private boolean IS_NO_MAC_ADDRESS = false;
	public static boolean IS_FROM_CHECK_HB_TO_PRIORITY_LIST = false;

	private static final String TAG = CheckHBAsync.class.getSimpleName();

	public static String HB_STATUS = null;
	private String ID = null;
	private String STATUS = null;
	private String XML = null;

	/**
	 * The others section
	 */
	private Context context;
	private Utils connectivity;

	public CheckHBAsync(Context context) {
		connectivity = new Utils(context);

		this.context = context;
	}

	public CheckHBAsync(Context context, boolean get_data) {
		connectivity = new Utils(context);

		this.context = context;
	}

	@Override
	protected Boolean doInBackground(String... params) {
		ID = params[0];
		STATUS = params[1];

		return getData(ID, Integer.valueOf(STATUS));
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();

		if (context.getClass().getSimpleName().equals(Class.CLASS_PRIORITY_LIST)) {
			connectivity.showProgressDialog();
		}
	}

	@Override
	protected void onPostExecute(Boolean result) {
		super.onPostExecute(result);

		if (!result) {
			// Cancel time out timer
			/**
			 * Check Time Out timer is not null, set time out timer is null, If
			 * card still being status=stop
			 */
			if (define.PriorityList.timeoutTimer != null) {
				define.PriorityList.timeoutTimer.cancel();
				define.PriorityList.timeoutTimer = null;
			}

			if (IS_NO_MAC_ADDRESS) {
				Toast.makeText(context,
						context.getString(R.string.toast_no_mac_is_registered),
						Toast.LENGTH_SHORT).show();
			} else {
				connectivity.showConnectionTimeoutDialog(context, Home.class);
			}
		} else {
			new Handler().post(new Runnable() {

				@Override
				public void run() {
					checkData(XML);
				}
			});
		}

		if (context.getClass().getSimpleName().equals(Class.CLASS_PRIORITY_LIST)) {
			connectivity.hideProgressDialog();
		}
	}

	/**
	 * Basic methods
	 */

	public static void avoidChangeFileOrder() {
		// cannot move files when the button is Change Priority
		// refresh button should not appear when button is Change
		// priority
		if (PriorityList.mIbtnChangePriority.isShown()) {
			// If Change Priority button was shown,
			// Hide Refresh button
			// And not allow drag the item

			PriorityList.DragSortListViewPriorityList.setDragEnabled(false);
			// Hide Refresh button
			PriorityList.mIbtnRefresh.setVisibility(View.INVISIBLE);
		} else {
			// If Submit button was shown
			// Show Refresh button
			// And allow drag the item

			PriorityList.DragSortListViewPriorityList.setDragEnabled(true);
			// Show Refresh button
			PriorityList.mIbtnRefresh.setVisibility(View.VISIBLE);
		}
	}

	public static void avoidShowRefreshButton() {
		// refresh button should not appear when button is Change
		// priority
		if (PriorityList.mIbtnChangePriority.isShown()) {
			// Hide Refresh button
			PriorityList.mIbtnRefresh.setVisibility(View.INVISIBLE);
		} else {
			// Show Refresh button
			PriorityList.mIbtnRefresh.setVisibility(View.VISIBLE);
		}
	}

	private void connectedCard(String[] SPLITTED_XML) {
		if (context.getClass().getSimpleName().equals(Class.CLASS_HOME)) {
			// Home context
			Home.mTvCardStatus.setText(context
					.getString(R.string.card_is_connected));
		} else if (context.getClass().getSimpleName()
				.equals(Class.CLASS_PRIORITY_LIST)) {
			// Priority List context

			/**
			 * Check Time Out timer is not null, set time out timer is null, If
			 * card still being status=stop
			 */
			if (define.PriorityList.timeoutTimer != null) {
				define.PriorityList.timeoutTimer.cancel();
				define.PriorityList.timeoutTimer = null;
			}

			// Card status was gone
			PriorityList.mTvCardStatus.setVisibility(View.GONE);

			if (SPLITTED_XML[1].split(":")[1].equals(Constants.INIT)) {
				// Show Change Priority button, Hide Submit button
				PriorityList.mIbtnChangePriority.setVisibility(View.VISIBLE);
				PriorityList.mIbtnSubmit.setVisibility(View.GONE);

				if (PriorityList.IS_FIRST_TIME_TO_CHECK_HB) {
					PriorityList.IS_FIRST_TIME_TO_CHECK_HB = false;

					// Clear the list
					if (PriorityListAsync.mLlItems != null
							& !PriorityListAsync.mLlItems.isEmpty()) {
						PriorityListAsync.mLlItems.clear();
					}

					new PriorityListAsync(context).execute(ID, STATUS + "");
				}
			} else if (SPLITTED_XML[1].split(":")[1].equals(Constants.SUBMIT)) {
				Toast.makeText(context,
						"Oops! Please try to run application again!",
						Toast.LENGTH_SHORT).show();
			} else if (SPLITTED_XML[1].split(":")[1].equals(Constants.STOP)) {
				Toast.makeText(context,
						"Oops! Please try to run application again!",
						Toast.LENGTH_SHORT).show();

				// Show Change Priority button, Hide Submit button
				// PriorityList.mIbtnChangePriority.setVisibility(View.GONE);
				// PriorityList.mIbtnSubmit.setVisibility(View.GONE);
			} else if (SPLITTED_XML[1].split(":")[1].equals(Constants.STOPPED)) {
				// Show Change Priority button, Hide Submit button
				PriorityList.mIbtnChangePriority.setVisibility(View.GONE);
				PriorityList.mIbtnSubmit.setVisibility(View.VISIBLE);
			}

			avoidChangeFileOrder();
			avoidShowRefreshButton();
		}
	}

	private void disconnectedCard(String[] SPLITTED_XML) {
		if (context.getClass().getSimpleName().equals(Class.CLASS_HOME)) {
			// Home context
			Home.mTvCardStatus.setText(context
					.getString(R.string.card_is_disconnected));
		} else if (context.getClass().getSimpleName()
				.equals(Class.CLASS_PRIORITY_LIST)) {
			// Priority List context

			/**
			 * Check Time Out timer is not null, set time out timer is null, If
			 * card still being status=stop
			 */
			if (define.PriorityList.timeoutTimer != null) {
				define.PriorityList.timeoutTimer.cancel();
				define.PriorityList.timeoutTimer = null;
			}

			// Display "Card is disconnected" bar
			PriorityList.mTvCardStatus.setVisibility(View.VISIBLE);
			PriorityList.mTvCardStatus.setText(context
					.getString(R.string.card_is_disconnected));

			// Hide Change Priority button, Show Submit button
			// PriorityList.mIbtnChangePriority.setVisibility(View.VISIBLE);
			if (!PriorityList.mIbtnChangePriority.isShown()) {
				PriorityList.mIbtnSubmit.setVisibility(View.VISIBLE);
			}

			avoidChangeFileOrder();
			avoidShowRefreshButton();

			if (PriorityList.IS_FIRST_TIME_TO_CHECK_HB) {
				PriorityList.IS_FIRST_TIME_TO_CHECK_HB = false;

				IS_FROM_CHECK_HB_TO_PRIORITY_LIST = true;

				// Clear the list
				if (PriorityListAsync.mLlItems != null
						& !PriorityListAsync.mLlItems.isEmpty()) {
					PriorityListAsync.mLlItems.clear();
				}

				new PriorityListAsync(context).execute(ID,
						define.Status.STATUS_GET_LIST_OF_FILES + "" + "");
			}
		}
	}

	private void checkData(String XML) {
		String[] SPLITTED_XML = XML.split(",");

		HB_STATUS = SPLITTED_XML[0].split(":")[1];

		/**
		 * Get new HB status
		 */
		PriorityListAsync.CURRENT_STATUS_HB = HB_STATUS;

		if (HB_STATUS.equals(define.Status.STATUS_HB_CONNECTED + "")) {
			// Toast.makeText(context, "HB : " + HB_STATUS, Toast.LENGTH_SHORT)
			// .show();
			/**
			 * HB = 1 : Connected card
			 */
			connectedCard(SPLITTED_XML);
		} else if (HB_STATUS.equals(define.Status.STATUS_HB_DISCONNECTED + "")) {
			// Toast.makeText(context, "HB : " + HB_STATUS, Toast.LENGTH_SHORT)
			// .show();
			/**
			 * HB = 0 : Disconnected card
			 */
			disconnectedCard(SPLITTED_XML);
		}
	}

	public boolean getData(String ID, int KEY_STATUS) {
		try {
			HttpClient mHttpClient = new DefaultHttpClient();
			HttpPost mHttpPost = new HttpPost(API.DOWNLOAD_LIST_REQUEST);
			List<NameValuePair> mNameValues = new ArrayList<NameValuePair>(2);

			/**
			 * Get HB
			 */
			// 1.user_id
			mNameValues.add(new BasicNameValuePair(Key.KEY_USER_ID, ID));

			// 2.status=refresh
			// when refresh, should get new updated list file
			switch (KEY_STATUS) {
			case define.Status.STATUS_HB:
				// 2.status=HB
				mNameValues.add(new BasicNameValuePair(Key.KEY_STATUS,
						Constants.HB + ""));
				break;
			case define.Status.STATUS_STOP:
				// 2.status=Stop
				if (context.getClass().getSimpleName()
						.equals(Class.CLASS_PRIORITY_LIST)) {
					mNameValues.add(new BasicNameValuePair(Key.KEY_STATUS,
							Constants.STOP + ""));
				}
				break;
			case define.Status.STATUS_SUBMIT:
				// 2.status=Submit
				if (context.getClass().getSimpleName()
						.equals(Class.CLASS_PRIORITY_LIST)) {
					mNameValues.add(new BasicNameValuePair(Key.KEY_STATUS,
							Constants.SUBMIT + ""));
				}
				break;
			default:
				break;
			}

			mHttpPost.setEntity(new UrlEncodedFormEntity(mNameValues));

			HttpResponse mHttpResponse = mHttpClient.execute(mHttpPost);
			HttpEntity mHttpEntity = mHttpResponse.getEntity();

			XML = EntityUtils.toString(mHttpEntity);
			if (XML == null) {
				//return false;
				Toast.makeText(context, context.getString(R.string.toast_user_may_not_have_a_card), Toast.LENGTH_LONG).show();
			}

			/**
			 * If No MAC is registered for userID
			 */
			if (XML.equals(context.getString(R.string.no_mac_is_registered)
					+ " " + Long.valueOf(ID) + ".")) {
				// No MAC is registered for userID
				IS_NO_MAC_ADDRESS = true;

				return false;
			}

			return true;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (ConnectTimeoutException e) {
			e.printStackTrace();
			return false;
		} catch (SocketException e) {
			e.printStackTrace();
			return false;
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}
}
